package org.infodavid.common.persistence.impl;

import javax.persistence.PersistenceException;

import org.infodavid.common.model.impl.AbstractDataObjectImpl;
import org.infodavid.common.persistence.ConnectionHelperRegistry;
import org.infodavid.common.persistence.IConnectionConfiguration;
import org.infodavid.common.persistence.IDatabaseHost;
import org.infodavid.common.persistence.IDatabaseSchema;

/**
 * The Class DatabaseSchemaImpl.
 */
public class DatabaseSchemaImpl extends AbstractDataObjectImpl<Long> implements IDatabaseSchema {

  /** serialVersionUID. */
  private static final long serialVersionUID = -6474625515242390309L;

  /** The name. */
  private String name;

  /** The JNDI name. */
  private String jndiName;

  /** The user password. */
  private String password;

  /** The user name. */
  private String username;

  /** The comment. */
  private String comment;

  /** The host. */
  private IDatabaseHost host;

  /** The status. */
  private ESchemaStatus status;

  /**
   * constructor.
   * @throws Exception the exception
   */
  public DatabaseSchemaImpl() throws Exception {
    super();
  }

  /**
   * constructor.
   * @param keyArg the key
   * @throws Exception the exception
   */
  public DatabaseSchemaImpl(final Long keyArg) throws Exception {
    super();

    setKey(keyArg);
  }

  /*
   * See super class or interface. (non-Javadoc)
   * @see org.infodavid.common.model.impl.DataObjectImpl#init()
   */
  @Override
  public void init() throws Exception {
    super.init();

    host = null;
    jndiName = null;
    username = null;
    password = null;
    name = null;
    comment = null;
    status = ESchemaStatus.MAINTENANCE;
  }

  /*
   * See super class or interface. (non-Javadoc)
   * @see org.infodavid.common.persistence.IDatabaseSchema#getStatus()
   */
  @Override
  public ESchemaStatus getStatus() {
    return status;
  }

  /*
   * See super class or interface. (non-Javadoc)
   * @see org.infodavid.common.persistence.IDatabaseSchema#getName()
   */
  @Override
  public String getName() {
    return name;
  }

  /*
   * See super class or interface. (non-Javadoc)
   * @see org.infodavid.common.persistence.IDatabaseSchema#getHost()
   */
  @Override
  public IDatabaseHost getHost() {
    return host;
  }

  /*
   * See super class or interface. (non-Javadoc)
   * @see org.infodavid.common.model.ICommented#getComment()
   */
  @Override
  public String getComment() {
    return comment;
  }

  /*
   * See super class or interface. (non-Javadoc)
   * @see org.infodavid.common.persistence.IDatabaseSchema#getJndiName()
   */
  @Override
  public String getJndiName() {
    return jndiName;
  }

  /*
   * See super class or interface. (non-Javadoc)
   * @see org.infodavid.common.persistence.IDatabaseSchema#getPassword()
   */
  @Override
  public String getPassword() {
    return password;
  }

  /*
   * See super class or interface. (non-Javadoc)
   * @see org.infodavid.common.persistence.IDatabaseSchema#getUsername()
   */
  @Override
  public String getUsername() {
    return username;
  }

  /*
   * See super class or interface. (non-Javadoc)
   * @see org.infodavid.common.persistence.IDatabaseSchema#setName(java.lang.String)
   */
  @Override
  public void setName(final String value) {
    if (!equals(name, value)) {
      final Object old = name;
      name = value;
      markModified(NAME, old, name);
    }
  }

  /*
   * See super class or interface. (non-Javadoc)
   * @see
   * org.infodavid.common.persistence.IDatabaseSchema#setStatus(org.infodavid.common.persistence.
   * IDatabaseSchema.ESchemaStatus)
   */
  @Override
  public void setStatus(final ESchemaStatus value) {
    if (!equals(status, value)) {
      final Object old = status;
      status = value;
      markModified(STATUS, old, status);
    }
  }

  /*
   * See super class or interface. (non-Javadoc)
   * @see org.infodavid.common.model.ICommented#setComment(java.lang.String)
   */
  @Override
  public void setComment(final String value) {
    if (!equals(comment, value)) {
      final Object old = comment;
      comment = value;
      markModified(COMMENT, old, comment);
    }
  }

  /*
   * See super class or interface. (non-Javadoc)
   * @see org.infodavid.common.persistence.IDatabaseSchema#setHost(org.infodavid.common.persistence.
   * IDatabaseHost )
   */
  @Override
  public void setHost(final IDatabaseHost value) {
    if (!equals(host, value)) {
      final Object old = host;
      host = value;
      markModified(HOST, old, host);
    }
  }

  /*
   * See super class or interface. (non-Javadoc)
   * @see org.infodavid.common.persistence.IDatabaseSchema#setJndiName(java.lang.String)
   */
  @Override
  public void setJndiName(final String value) {
    if (!equals(jndiName, value)) {
      final Object old = jndiName;
      jndiName = value;
      markModified(JNDI_NAME, old, jndiName);
    }
  }

  /*
   * See super class or interface. (non-Javadoc)
   * @see org.infodavid.common.persistence.IDatabaseSchema#setPassword(java.lang.String)
   */
  @Override
  public void setPassword(final String value) {
    if (!equals(password, value)) {
      final Object old = password;
      password = value;
      markModified(PASSWORD, old, password);
    }
  }

  /*
   * See super class or interface. (non-Javadoc)
   * @see org.infodavid.common.persistence.IDatabaseSchema#setUsername(java.lang.String)
   */
  @Override
  public void setUsername(final String value) {
    if (!equals(username, value)) {
      final Object old = username;
      username = value;
      markModified(USERNAME, old, username);
    }
  }

  /*
   * See super class or interface. (non-Javadoc)
   * @see org.infodavid.common.model.impl.DataObjectImpl#toString(java.lang.StringBuffer)
   */
  @Override
  protected StringBuffer toString(final StringBuffer builder) {
    super.toString(builder);

    builder.append(" [comment=");
    builder.append(comment);
    builder.append(", host=");

    if (password == null) {
      builder.append("null");
    }
    else {
      builder.append(host.getKey());
    }

    builder.append(", jndiName=");
    builder.append(jndiName);
    builder.append(", name=");
    builder.append(name);
    builder.append(", password=");

    if (password == null) {
      builder.append("null");
    }
    else {
      builder.append(password.replace(".*", "#"));
    }

    builder.append(", username=");
    builder.append(username);
    builder.append(", status=");
    builder.append(status);
    builder.append("]");

    return builder;
  }

  /*
   * See super class or interface. (non-Javadoc)
   * @see org.infodavid.common.persistence.IDatabaseSchema#toConnectionConfiguration()
   */
  @Override
  public IConnectionConfiguration toConnectionConfiguration() throws PersistenceException {
    final IConnectionConfiguration configuration;

    configuration = new ConnectionConfigurationImpl();

    configuration.setName(getName());

    if (host == null) {
      LOGGER.debug("Host of schema: " + getName() + " is null");
    }
    else {
      configuration.setHost(getHost().getName());
      configuration.setJdbcDriver(getHost().getJdbcDriver());
      configuration.setTcpPort(getHost().getTcpPort());
      configuration.setType(getHost().getType());
    }

    configuration.setJndiName(getJndiName());
    configuration.setPassword(getPassword());
    configuration.setSchema(getName());
    configuration.setStdConnectionString(ConnectionHelperRegistry.getInstance()
        .getConnectionString(configuration));
    configuration.setUser(getUsername());

    return configuration;
  }

  /*
   * (non-Javadoc)
   * @see org.infodavid.common.model.impl.DataObjectImpl#hashCode()
   */
  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + (getHost() == null ? 0 : getHost().hashCode());
    result = prime * result + (getName() == null ? 0 : getName().hashCode());

    return prime * result + (getUsername() == null ? 0 : getUsername().hashCode());
  }

  /*
   * (non-Javadoc)
   * @see org.infodavid.common.model.impl.DataObjectImpl#equals(java.lang.Object)
   */
  @Override
  public boolean equals(final Object obj) {
    if (this == obj) {
      return true;
    }

    if (obj == null) {
      return false;
    }

    if (!(obj instanceof IDatabaseSchema)) {
      return false;
    }

    final IDatabaseSchema other = (IDatabaseSchema)obj;

    if (getHost() == null) {
      if (other.getHost() != null) {
        return false;
      }
    }
    else if (!getHost().equals(other.getHost())) {
      return false;
    }

    if (getName() == null) {
      if (other.getName() != null) {
        return false;
      }
    }
    else if (!getName().equals(other.getName())) {
      return false;
    }

    if (getUsername() == null) {
      if (other.getUsername() != null) {
        return false;
      }
    }
    else if (!getUsername().equals(other.getUsername())) {
      return false;
    }

    return true;
  }
}
